<?php
/**
 * CreateTime: 2023/11/16 11:46
 * User:LinQ
 */

namespace App\Func\User;

use App\Models\Auth\AuthModel;
use App\Models\Auth\RoleAuthModel;
use App\Models\Users\UsersModel;
use Illuminate\Support\Facades\Hash;

class UserFunc
{
    /**
     * 默认的用户密码的规则
     * @param string $pass 传入明文生成用户的原始密码
     * @return string
     */
    public function getHashPassByUser(string $pass): string{
        return \Illuminate\Support\Facades\Hash::make($pass.env('APP_KEY'));
    }

    /**
     * 校验用户密码
     * @param string $pass 用户密码
     * @param string $hash_pass 加密过的密码
     * @return bool 校验通过返回true 否则返回false
     */
    public function checkHashPassByUser(string $pass,string $hash_pass): bool{
        if (Hash::check($pass.env('APP_KEY'),$hash_pass)) {
            return true;
        }
        return false;
    }

    /**
     * 校验用户签名以及是否切换设备 并且返回当前登录用户的id uuid等
     * @param string $utk 支持手动传入utk
     * @param string $u_dept 支持手动传入用户部门
     * @param bool $canAll 是否显示公私钥
     * @return mixed
     */
    public function getLoginInfo($utk = "",$u_dept = "",$canAll = false): mixed
    {
        if(!$utk){
            $utk = request()->header('U-TK');
        }
        if(!$utk){
            s_fail_return(null,trans('message.auth_checker_err',[
                'code' => 1001
            ]),
                status:false,
                code:'Unauthorized',
                httpCode: 401
            );
        }

        if(!$u_dept){
            $u_dept = request()->header('U-DEPT');
        }
        if(!$u_dept){
            s_fail_return(null,trans('message.auth_checker_err',[
                'code' => 1006
            ]),
                status:false,
                code:'Unauthorized',
                httpCode: 401
            );
        }

        $utkInfo = explode('.',$utk);
        // headerInfo
        $headerInfo = json_decode(base64_decode($utkInfo[0]),true);
        $payloadInfo = json_decode(base64_decode($utkInfo[1]),true);
        $sign = $utkInfo[2];
        $deadline = $headerInfo['deadline'];
        // TODO 暂时注释
//        if(time()>$deadline){
//            s_fail_return(null,'登录已过期,请重新登录',
//                status:false,
//                code:'Unauthorized',
//                httpCode: 401
//            );
//        }
        if($headerInfo['alg'] == 'HS256'){
            $sg = base64_encode(hash_hmac('sha256', "$utkInfo[0].$utkInfo[1].$utkInfo[3]", md5(json_encode($utkInfo[1],true)), true));
        }else{
            $sg = "";
        }
        if($sg!=$sign){
            s_fail_return(null,trans('message.auth_checker_err',[
                'code' => 1002
            ]),
                status:false,
                code:'Unauthorized',
                httpCode: 401
            );
        }
        $ipInfo = aes_256_cbc_pkcs7_decode($utkInfo[3],md5($payloadInfo['user_id']));
        // TODO 暂时注释
//        if($ipInfo!=request()->ip()){
//            s_fail_return(null,trans('message.auth_checker_err',[
//                'code' => 1003
//            ]),
//                status:false,
//                code:'Unauthorized',
//                httpCode: 401
//            );
//        }
        // 校验用户的hash编码是否能够对应
        // 获取用户信息
        $userInfo = UsersModel::with(['departments'=>function($query){
            $query->select([
                'department.department_id',
                'department.department_name',
            ]);
        }])->find($payloadInfo['user_id']);




        $departments = $userInfo->departments->toArray();
        $mapDepartments = array_column($departments,'department_id');

        if(!in_array($u_dept,$mapDepartments)){
            s_fail_return(null,trans('message.auth_checker_err',[
                'code' => 1005
            ]),
                status:false,
                code:'Unauthorized',
                httpCode: 401
            );
        }

        $fmtDepartments = [];
        foreach($departments as $v){
            $fmtDepartments[] = [
                'department_id' => $v['department_id'],
                'pivot' => $v['pivot'],
            ];
        }

        if($payloadInfo['hash'] != hash_sign_x1($userInfo->password.json_encode($fmtDepartments,256))){
            s_fail_return(null,trans('message.auth_checker_err',[
                'code' => 1004
            ]),
                status:false,
                code:'Unauthorized',
                httpCode: 401
            );
        }
        $userInfoArr = $userInfo->toArray();
        if($canAll){
            $userInfoArr['pv_key'] = $userInfo->pv_key;
            $userInfoArr['pu_key'] = $userInfo->pu_key;
        }
        return $userInfoArr;
    }


    /**
     * 获取用户的权限
     * @param int $user_id
     * @return array
     */
    public function getUserAuth(int $user_id,$select = ["*"]): array{
        $userInfo = \App\Models\Users\UsersModel::find($user_id);
        if(!$userInfo){
            return [];
        }
        return $userInfo->auths($select);
    }

    /**
     * 获取用户们的权限
     * @param array $user_ids [1,2,3,4]
     * @return array
     */
    public function getUsersAuth(array $user_ids): array
    {
        $users = \App\Models\Users\UsersModel::whereIn('user_id', $user_ids)->get();
        return $users->map(function ($user) {
            return [
                'user_id' => $user->user_id,
                'auths' => $user->auths()
            ];
        })->toArray();
    }

    /**
     * 查看当前用户是否有这个角色
     * @param int $user_id 用户id
     * @param int $role_id 权限id
     * @return bool 如果没有这个角色则直接返回false
     */
    public function hasRole(int $user_id,int $role_id): bool
    {
        $roles = UsersModel::with('roles')->find($user_id)->roles->toArray();
        $roleIds = array_column($roles,'role_id');
        if(in_array($role_id,$roleIds)){
            return true;
        }
        return false;
    }

    /**
     *  查看当前用户是否有这个权限
     * @param int $user_id 用户id
     * @param string|int $auth 权限id或者权限code 自动判断数字则为id 字符串为code
     * @return bool 如果没有这个权限则直接返回false
     */
    public function hasAuth(int $user_id,string | int $auth) : bool{
        $auths = UsersModel::find($user_id)->auths();
        if(is_int($auth)){
            $authsIds = array_column($auths,'auth_id');
            if(in_array($auth,$authsIds)){
                return true;
            }
            return false;
        }

        if(is_string($auth)){
            $authsCodes = array_column($auths,'auth_code');
            if(in_array($auth,$authsCodes)){
                return true;
            }
        }
        return false;
    }

    /**
     * 是否拥有这个权限
     * @param string $authCode 权限code
     * @param int|string $value 权限value 基础的权限 1读 2写 4修改 8删除 可自定义拓展
     */
    public function canAuths(string $authCode, int|string $value) :bool{
        // 默认获取当前登录用户信息
        $user_id = $this->getLoginInfo()['user_id'];
        // 判断当前用户是否有这个权限，如果没有直接返回false
        $hasAuth = $this->hasAuth($user_id,$authCode);
        if(!$hasAuth){
            return false;
        }
        $authInfo = (new AuthModel())->getAuthInfoByAuthCode($authCode);
        $userModel = new UsersModel();
        $userInfo = $userModel->find($user_id);
        // 获取用户的角色组 转化为 ids
        $userRoles = $userModel->with(['roles'=>function($query) use ($userInfo){
            $query->where('com_id',$userInfo['com_id']);
        }])->find($user_id)->roles->toArray();
        $userRoleIds = array_column($userRoles,'role_id');
        // 根据角色组和权限获取最大的权限值
        $maxValue = (new RoleAuthModel())->getRoleAuthByRolesAndAuthId($userRoleIds,$authInfo['auth_id']);
        // 如果权限类型为 2菜单权限 3布尔权限 不为0 则返回true
        if($authInfo['auth_type'] == 2 || $authInfo['auth_type'] == 3){
            if($maxValue){
                return true;
            }
        // 如果权限类型为 1一般权限 则需要与 value 权限进行 位与运算
        }else if($authInfo['auth_type'] == 1){
            return $value&&$maxValue;
        }
        return false;
    }

    /**
     * 获取用户公司id
     * @return mixed
     */
    public function getCurrentComId(): mixed
    {
        return $this->getLoginInfo()['com_id'];
    }

}
